package com.bsj.power.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Validator;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.crypt.crypt.aes.AESUtils;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.config.global.TokenUser;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.constant.AlarmEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.PageDTO;
import com.bsj.power.common.def.dto.user.UserAddDTO;
import com.bsj.power.common.def.dto.user.UserModifyPasswordDTO;
import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
import com.bsj.power.common.def.entity.log.SystemOpLog;
import com.bsj.power.common.def.entity.menu.Menu;
import com.bsj.power.common.def.entity.menu.RoleMenu;
import com.bsj.power.common.def.entity.personGroup.PersonGroup;
import com.bsj.power.common.def.entity.role.Role;
import com.bsj.power.common.def.entity.role.UserRole;
import com.bsj.power.common.def.entity.sys.SystemConfig;
import com.bsj.power.common.def.entity.user.User;
import com.bsj.power.common.def.entity.userOperateLog.UserOperateLog;
import com.bsj.power.common.def.enums.SystemOpTypeEnum;
import com.bsj.power.common.def.enums.VideoOpTypeEnum;
import com.bsj.power.common.def.vo.web.system.user.UserVO;
import com.bsj.power.common.mapper.*;
import com.bsj.power.common.util.*;
import com.bsj.power.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yinhao
 * @version 1.0
 * @description ???
 * @date 2024/4/22
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private SystemOpLogMapper systemOpLogMapper;

    @Resource
    private PersonGroupMapper personGroupMapper;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Resource
    private MenuMapper menuMapper;

    @Autowired
    private RedisCached redisCached;

    @Resource
    private UserOperateLogMapper userOperateLogMapper;

    /**
     * 用户登录 (参数传输过程需要base64编码)
     * 1、用户初次登录时，应用系统应强制要求修改初始口令，且前后修改的口令不能完全相同；与前端约定以首次登录时间是否为空来判断是否修改过密码
     * 首次登录时间在修改密码后再填充，修改密码后强制重新登录
     * 2、应用系统应具备用户账号连续登录失败的处理机制，针对连续登录失败次数（不超过10次）达到预设值的用户账号进行锁定，至少锁定30分钟或授权管理员解锁（暂时只针对密码错误）
     * 3、应用系统应提供口令有效期（不超过6个月）限制功能，在鉴别身份之前，应能检验用户口令是否过期，并强制要求用户修改过期的口令，且新口令满足复杂度要求
     *
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @Override
    @Transactional
    public JsonResult login(String username, String password, HttpServletRequest request) {
        String decodeUserName = Base64.decodeStr(username);
        String decodePassword = Base64.decodeStr(password);
        User user = userMapper.selectCryptUserInfo(decodeUserName);
        if (user == null) {
            return JsonResult.fail(JsonResultEnum.USER_INFO_ISNULL);
        }
        Long userId = user.getUserId();
        String userLockStr = redisCached.get(RedisConstant.USER_LOGIN_LOCK + userId);
        if (StringUtils.isNotBlank(userLockStr)) {
            return JsonResult.fail(JsonResultEnum.USER_LOCK);
        }
        Date date = new Date();
        //排除admin
        if (user.getParentId() != -1) {
            //三个月未使用设置休眠不允许访问
            if (DateUtils.differentDays(user.getLastLoginTime(), date) >= 90) {
                user.setIsAccess(NumericalConstants.TWO);
                userMapper.updateById(user);
                return JsonResult.fail("已超过三个月未使用本系统，账号已休眠，请联系管理员设置访问权限");
            }
            //无法访问
            if (user.getIsAccess().equals(NumericalConstants.TWO)) {
                return JsonResult.fail(JsonResultEnum.PERMISSION_EXCEPTION);
            }
        }

        boolean passwordMate = Objects.equals(user.getPassword(), decodePassword);
        //应用系统应具备用户账号连续登录失败的处理机制，针对连续登录失败次数（不超过10次）达到预设值的用户账号进行锁定，至少锁定30分钟或授权管理员解锁（暂时只针对密码错误）
        if (!passwordMate) {
            //排除admin
            if (user.getParentId() != -1) {
                //获取规则“连续登录失败次数预设值”，默认10次
                Integer failNumber = 10;
                //登录失败锁定时长(秒)默认30分钟
                Integer second = 60 * 30;
                String configStr = redisCached.get(RedisConstant.SYS_CONF_MODE);
                if (StringUtils.isNotBlank(configStr)) {
                    SystemConfig systemConfig = JSONObject.parseObject(configStr, SystemConfig.class);
                    if (systemConfig.getLoginFailNum() != null) {
                        failNumber = systemConfig.getLoginFailNum();
                    }
                    if (systemConfig.getLoginFailLock() != null) {
                        second = systemConfig.getLoginFailLock();
                    }
                }
                //已失败数量
                Integer alreadyFailNumber = NumericalConstants.ZERO;
                String str = redisCached.get(RedisConstant.LOGIN_ALREADY_FAIL_NUMBER + userId);
                if (StringUtils.isNotBlank(str)) {
                    alreadyFailNumber = Integer.parseInt(str);
                }
                alreadyFailNumber += NumericalConstants.ONE;
                //账号锁定
                if (alreadyFailNumber >= failNumber) {
                    redisCached.set(RedisConstant.USER_LOGIN_LOCK + userId, "无作用的值", second);
                    //清除次数
                    redisCached.del(RedisConstant.LOGIN_ALREADY_FAIL_NUMBER + userId);
                    return JsonResult.fail(JsonResultEnum.USER_LOCK);
                } else {
                    redisCached.set(RedisConstant.LOGIN_ALREADY_FAIL_NUMBER + userId, alreadyFailNumber);
                }
            }
            return JsonResult.fail(JsonResultEnum.PASSWORD_ERROR);
        }
        //登录状态写入
        StpUtil.login(userId);
        TokenUser tokenUser = new TokenUser();
        BeanUtils.copyProperties(user, tokenUser);
        tokenUser.setUserName(decodeUserName);
        tokenUser.setUserType(NumericalConstants.ZERO);
        String tokenValue = StpUtil.getTokenValue();
        //24小时过期
//        StpUtil.renewTimeout(tokenValue, 24 * 60 * 60);
        tokenUser.setSessionId(tokenValue);
        //排除admin
        if (user.getParentId() != -1) {
            //首次登录修改密码
            if (user.getFirstLoginTime() == null) {
                tokenUser.setIsUpdatePassword(NumericalConstants.ONE);
            }
            //六个月必须修改密码
            if (DateUtils.differentDays(user.getPasswordUpdateTime(), date) >= 180) {
                tokenUser.setIsUpdatePassword(NumericalConstants.TWO);
            }
        }
        List<Long> roleIds = userRoleMapper.selectUserRoleIdList(userId);
        if (!roleIds.isEmpty()) {
            List<Role> roleInfoList = roleMapper.selectBatchIds(roleIds);
            //目前是一个用户只有一个角色
            if (!roleInfoList.isEmpty()) {
                Role role = roleInfoList.get(0);
                tokenUser.setRoleSign(role.getRoleSign());
                tokenUser.setRoleType(role.getRoleType());
                Long roleId = role.getRoleId();
                List<RoleMenu> roleMenus = roleMenuMapper.selectList(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));
                if (!roleMenus.isEmpty()) {
                    List<Integer> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
                    List<Menu> menus = menuMapper.selectList(Wrappers.<Menu>lambdaQuery().in(Menu::getMenuId, menuIds));
                    if (!menus.isEmpty()) {
                        List<String> menuSigns = menus.stream().map(Menu::getMenuSign).collect(Collectors.toList());
                        tokenUser.setMenuSigns(menuSigns);
                    }
                }
            }
        }
        StpUtil.getTokenSession().set("loginUser", tokenUser);
        log.info("登录用户信息{}", tokenUser);
//        try {
//            TokenUser tokenInfo = StpLoginUserUtil.getTokenUser();
//            if (tokenInfo != null) {
//                SystemOpLog systemOpLog = new SystemOpLog();
//                int type = SystemOpTypeEnum.LOGIN.getOpType();
//                systemOpLog.setOpUserId(tokenInfo.getUserId());
//                systemOpLog.setOpUserName(tokenInfo.getUserName());
//                systemOpLog.setName(VideoOpTypeEnum.getByValue(type));
//                systemOpLog.setOpType(type);
//                systemOpLog.setOpTime(date);
//                systemOpLog.setCreateTime(date);
//                UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
//                systemOpLog.setIp(request.getRemoteAddr().equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : request.getRemoteAddr());
//                systemOpLog.setBrowser(userAgent.getBrowser().toString());
//                systemOpLog.setOs(userAgent.getOs().toString());
//                systemOpLogMapper.insert(systemOpLog);
//            }
//        } catch (Exception e) {
//            log.error("记录日志失败：{}", ExceptionUtil.getStackStr(e));
//        }
        user.setLastLoginTime(date);
        userMapper.updateById(user);
        //清除次数
        redisCached.del(RedisConstant.LOGIN_ALREADY_FAIL_NUMBER + userId);
        return JsonResult.success(tokenUser);
    }

    /**
     * 修改用户密码
     *
     * @param dto
     * @return
     */
    @Override
    public int modifyPassWord(UserModifyPasswordDTO dto, String ip) {
        Long userId = dto.getUserId();
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        if (userId == null) {
            userId = tokenUser.getUserId();
        }
        String newPassword = dto.getNewPassword();
        if (!StpLoginUserUtil.isPasswordStrong(newPassword)) {
            throw new ApiException(JsonResultEnum.PASSWORD_CHECK_FAIL);
        }
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException(JsonResultEnum.USER_NOT_EXIST);
        }
        String oldPassword = dto.getPassword();
        if (oldPassword.equals(newPassword)) {
            throw new ApiException(JsonResultEnum.PASSWORD_ARE_EQUAL);
        }
        boolean passwordMate = Objects.equals(oldPassword, user.getPassword());
        if (!passwordMate) {
            throw new ApiException(JsonResultEnum.PASSWORD_ERROR);
        }
        User newUser = new User();
        newUser.setUserId(userId);
        newUser.setPassword(newPassword);
        Date date = new Date();
        //填充首次登录时间
        if (user.getFirstLoginTime() == null) {
            newUser.setFirstLoginTime(date);
        }
        newUser.setPasswordUpdateTime(date);
        int count = userMapper.updateById(newUser);

        UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.ONE, ip, tokenUser);
        userOperateLog.setContentOperate(user.getUserName() + "账号修改密码不显示修改内容");
        userOperateLogMapper.insert(userOperateLog);
        return count;
    }

    /**
     * 重置密码
     *
     * @param userId
     * @return
     */
    @Override
    public String resetPassword(Long userId, String ip) {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        Long loginUserId = tokenUser.getUserId();
        Long parentId = tokenUser.getParentId();
        if (loginUserId.equals(userId)) {
            throw new ApiException(JsonResultEnum.NOT_RESET_MYSELF_PASSWORD);
        }
        if (parentId != -1) {
            //不是系统超级管理员,无法操作
            throw new ApiException(JsonResultEnum.USER_IS_NOT_ADMIN_UN_OPERATE);
        }
        User oldUser = userMapper.selectById(userId);
        ParamCheckUtil.isNull(oldUser, JsonResultEnum.USER_INFO_ISNULL);
        String passwordStr = RandomUtil.generateRandomString(8);
        log.info("用户重置密码用户ID: {}, 重置的密码: {}", userId, passwordStr);
        //固定在前端加#字符
        passwordStr = "#" + passwordStr;
        User newUser = new User();
        newUser.setUserId(userId);
        newUser.setPassword(passwordStr);
        newUser.setPasswordUpdateTime(new Date());
        userMapper.updateById(newUser);

        UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.ONE, ip, tokenUser);
        userOperateLog.setContentOperate(oldUser.getUserName() + "账号重置密码不显示修改内容");
        userOperateLogMapper.insert(userOperateLog);
        return passwordStr;
    }

    /**
     * 新增和修改用户
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addAndUpdateUser(UserAddDTO dto, String ip) {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        Long tokenUserUserId = tokenUser.getUserId();
        Long parentId = tokenUser.getParentId();
        if (parentId != -1) {
            //不是系统超级管理员,无法操作
            throw new ApiException(JsonResultEnum.USER_IS_NOT_ADMIN_UN_OPERATE);
        }
        Long userId = dto.getUserId();
        String userName = dto.getUserName();
        String phone = dto.getPhone();
        String password = dto.getPassword();
        User user = userMapper.selectCryptUserInfo(userName);
        User oldUser = null;
        if (userId == null) {
            //新增
            if (user != null) {
                throw new ApiException(JsonResultEnum.USER_NAME_EXIST);
            }
        } else {
            //修改
            oldUser = userMapper.selectById(userId);
            ParamCheckUtil.isNull(oldUser, JsonResultEnum.USER_NOT_EXIST);
            if (!oldUser.getUserName().equals(userName)) {
                //代表修改用户名,则代表需要修改的用户名不能存在
                if (user != null) {
                    throw new ApiException(JsonResultEnum.USER_UPDATE_NAME_EXIST);
                }
            }
        }
        //密码强度校验
        if (password != null && !StpLoginUserUtil.isPasswordStrong(password)) {
            throw new ApiException(JsonResultEnum.PASSWORD_CHECK_FAIL);
        }
        //手机号校验
        if (phone != null && !Validator.isMobile(phone)) {
            throw new ApiException(JsonResultEnum.PHONE_FORMAT_ERROR);
        }
        String roleName = null;
        //角色数据校验
        if (dto.getRoleId() != null) {
            QueryWrapper<Role> queryWrapper = new QueryWrapper();
            Role role = roleMapper.selectOne(queryWrapper.lambda().eq(Role::getRoleId, dto.getRoleId()));
            if (role == null) {
                throw new ApiException(JsonResultEnum.USER_ROLE_ISNULL);
            }
            roleName = role.getRoleName();
        }
        //用户组校验
        String groupName = null;
        Integer groupId = dto.getGroupId();
        if (groupId != null) {
            PersonGroup personGroup = personGroupMapper.selectOne(Wrappers.<PersonGroup>lambdaQuery()
                    .eq(PersonGroup::getGroupType, NumericalConstants.ONE).eq(PersonGroup::getGroupId, groupId));
            ParamCheckUtil.isNull(personGroup, JsonResultEnum.PERSON_GROUP_EXIST);
            groupName = personGroup.getGroupName();
        }
        User info = new User();
        info.setUserWeight(dto.getUserWeight());
        info.setUserId(userId);
        info.setUserName(userName.trim());
        info.setPhone(phone);
        info.setParentId(StpLoginUserUtil.getTokenUser().getUserId());
        if (groupId == null) {
            info.setGroupId(NumericalConstants.ZERO);
        } else {
            info.setGroupId(groupId);
        }
        //密码加密
        if (password != null) {
            info.setPassword(password);
        }
        if (userId == null) {
            //新增用户
            info.setParentId(tokenUserUserId);
            info.setIsAccess(NumericalConstants.ONE);
            addUser(info, dto.getRoleId());
            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.ONE, NumericalConstants.ONE, ip, tokenUser);
            setUserOperateContent(NumericalConstants.ONE, info, null, roleName, null, groupName, null, userOperateLog);
            userOperateLogMapper.insert(userOperateLog);
        } else {
            String oldRoleName = getOldRoleName(oldUser.getUserId());
            String oldGroupName = getOldGroupName(oldUser.getGroupId());
            //修改用户
            updateUser(info, dto.getRoleId());
            //保存用户操作日志
            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.ONE, ip, tokenUser);
            setUserOperateContent(NumericalConstants.TWO, info, oldUser, roleName, oldRoleName, groupName, oldGroupName, userOperateLog);
            userOperateLogMapper.insert(userOperateLog);
        }
        return info.getUserId();
    }

    /**
     * 获取之前绑定的用户组名称
     *
     * @param oldGroupId
     * @return java.lang.String
     * @author ljx
     * @time 2024/10/17 10:40
     */
    private String getOldGroupName(Integer oldGroupId) {
        if (oldGroupId != null) {
            PersonGroup personGroup = personGroupMapper.selectById(oldGroupId);
            if (personGroup != null) {
                return personGroup.getGroupName();
            }
        }
        return null;
    }

    /**
     * 获取之前绑定的角色名称
     *
     * @param userId
     * @return java.lang.String
     * @author ljx
     * @time 2024/10/17 10:39
     */
    private String getOldRoleName(Long userId) {
        List<Long> roleIds = userRoleMapper.selectUserRoleIdList(userId);
        if (!CollectionUtils.isEmpty(roleIds)) {
            Role oldRole = roleMapper.selectById(roleIds.get(NumericalConstants.ZERO));
            if (oldRole != null) {
                return oldRole.getRoleName();
            }
        }
        return null;
    }

    /**
     * 设置用户操作内容
     *
     * @param operateType    1新增 2修改 3删除
     * @param newUser        新用户信息
     * @param oldUser        旧用户信息
     * @param newRoleName
     * @param oldRoleName
     * @param userOperateLog
     * @return void
     * @author ljx
     * @time 2024/10/17 10:28
     */
    private void setUserOperateContent(Integer operateType, User newUser, User oldUser, String newRoleName, String oldRoleName, String newGroupName, String oldGroupName, UserOperateLog userOperateLog) {
        StringBuilder builder = new StringBuilder();
        if (operateType.equals(NumericalConstants.ONE)) {
            //新增
            builder.append("账号：").append(newUser.getUserName()).append("，");
            builder.append("用户权重：").append(newUser.getUserWeight()).append("，");
            builder.append("手机号：").append(newUser.getPhone()).append("，");
            builder.append("角色：").append(newRoleName).append("，");
            if (StringUtils.isNotBlank(newGroupName)) {
                builder.append("分组：").append(newGroupName);
            }
        } else if (operateType.equals(NumericalConstants.TWO)) {
            //修改（只记录修改的内容）
            //系统自带用户
            if (!newUser.getUserName().equals(oldUser.getUserName())) {
                builder.append("账号由").append(oldUser.getUserName()).append("修改为").append(newUser.getUserName()).append("，");
            }
            if (!newUser.getUserWeight().equals(oldUser.getUserWeight())) {
                builder.append("用户权重由").append(oldUser.getUserWeight()).append("修改为").append(newUser.getUserWeight()).append("，");
            }
            if (!newUser.getPhone().equals(oldUser.getPhone())) {
                builder.append("手机号由").append(oldUser.getPhone()).append("修改为").append(newUser.getPhone()).append("，");
            }
            if (StringUtils.isBlank(oldRoleName)) {
                oldRoleName = "- -";
            }
            if (!newRoleName.equals(oldRoleName)) {
                builder.append("角色由").append(oldRoleName).append("修改为").append(newRoleName).append("，");
            }
            if (StringUtils.isNotBlank(newGroupName)) {
                if (StringUtils.isNotBlank(oldGroupName)) {
                    if (!newGroupName.equals(oldGroupName)) {
                        builder.append("分组由").append(oldGroupName).append("修改为").append(newGroupName);
                    }
                } else {
                    builder.append("分组由").append("- -").append("修改为").append(newGroupName);
                }
            } else {
                if (StringUtils.isNotBlank(oldGroupName)) {
                    builder.append("分组由").append(oldGroupName).append("修改为").append("- -");
                }
            }
        } else {
            //删除
            builder.append("账号：").append(oldUser.getUserName()).append("，");
            builder.append("用户权重：").append(oldUser.getUserWeight()).append("，");
            builder.append("手机号：").append(oldUser.getPhone()).append("，");
            if (StringUtils.isNotBlank(oldRoleName)) {
                builder.append("角色：").append(oldRoleName).append("，");
            }
            if (StringUtils.isNotBlank(oldGroupName)) {
                builder.append("分组：").append(oldGroupName);
            }

        }
        String result = "";
        int length = builder.length();
        if (length != NumericalConstants.ZERO) {
            String substring = builder.substring(length - NumericalConstants.ONE);
            if (substring.equals("，")) {
                result = builder.substring(NumericalConstants.ZERO, length - NumericalConstants.ONE);
            } else {
                result = builder.toString();
            }
        }
        userOperateLog.setContentOperate(result);
    }

//    /**
//     * 设置用户操作内容
//     *
//     * @param isBefore       是否需要操作前内容
//     * @param isAfter        是否需要操作前内容
//     * @param userOperateLog
//     * @param userName
//     * @param oldUserName
//     * @param phone
//     * @param oldPhone
//     * @param roleName
//     * @param oldRoleName
//     * @param groupName
//     * @param oldGroupName
//     * @param userWeight
//     * @param oldUserWeight
//     * @return void
//     * @author ljx
//     * @time 2024/10/17 10:28
//     */
//    private void setUserOperateContent(Boolean isBefore, Boolean isAfter, UserOperateLog userOperateLog, String userName,
//                                       String oldUserName, String phone, String oldPhone, String roleName, String oldRoleName,
//                                       String groupName, String oldGroupName, Integer userWeight, Integer oldUserWeight) {
//        JSONObject jsonObject = new JSONObject();
//        if (isBefore) {
//            //操作前内容
//            jsonObject.put("userName", oldUserName);
//            jsonObject.put("phone", oldPhone);
//            jsonObject.put("roleName", oldRoleName);
//            jsonObject.put("groupName", oldGroupName);
//            jsonObject.put("userWeight", oldUserWeight);
//            userOperateLog.setContentBeforeOperate(jsonObject.toJSONString());
//        }
//        if (isAfter) {
//            //操作后内容
//            jsonObject.put("userName", userName);
//            jsonObject.put("phone", phone);
//            jsonObject.put("roleName", roleName);
//            jsonObject.put("groupName", groupName);
//            jsonObject.put("userWeight", userWeight);
//            userOperateLog.setContentAfterOperate(jsonObject.toJSONString());
//        }
//    }

    /**
     * 删除用户
     *
     * @param userId
     * @return
     */
    @Override
    public Integer deleteUser(Long userId, String ip) {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        Long tokenUserUserId = tokenUser.getUserId();
        Long parentId = tokenUser.getParentId();
        if (parentId != -1) {
            //不是系统超级管理员,无法操作
            throw new ApiException(JsonResultEnum.USER_IS_NOT_ADMIN);
        }
        User oldUser = userMapper.selectById(userId);
        if (oldUser == null) {
            throw new ApiException(JsonResultEnum.USER_NOT_EXIST);
        }
        if (oldUser.getUserId().equals(tokenUser.getUserId())) {
            throw new ApiException(JsonResultEnum.NOT_DELETE_ITSELF);
        }
        int count = userMapper.deleteById(userId);
        if (count >= NumericalConstants.ZERO) {
            String oldRoleName = getOldRoleName(oldUser.getUserId());
            String oldGroupName = getOldGroupName(oldUser.getGroupId());
            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.THREE, NumericalConstants.ONE, ip, tokenUser);
            setUserOperateContent(NumericalConstants.THREE, null, oldUser, null, oldRoleName, null, oldGroupName, userOperateLog);
            //删除绑定的角色关系
            userRoleMapper.delete(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, userId));
            //添加操作日志
            userOperateLogMapper.insert(userOperateLog);
        }
        return count;
    }

    /**
     * 新增用户
     *
     * @param user
     * @param roleId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addUser(User user, Long roleId) {
        int insert = userMapper.insert(user);
        if (insert > 0) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(roleId);
            userRoleMapper.insert(userRole);
        }
        return user.getUserId();
    }

    /**
     * 修改用户
     *
     * @param user
     * @param roleId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long updateUser(User user, Long roleId) {
        int updateById = userMapper.updateById(user);
        if (updateById > 0) {
            if (roleId != null) {
                List<UserRole> userRoles = new ArrayList<>();
                UpdateWrapper<UserRole> updateWrapper = new UpdateWrapper<>();
                userRoleMapper.delete(updateWrapper.lambda().eq(UserRole::getUserId, user.getUserId()));
                UserRole userRole = new UserRole();
                userRole.setUserId(user.getUserId());
                userRole.setRoleId(roleId);
                userRoleMapper.insert(userRole);
            }
        }
        return user.getUserId();
    }

    /**
     * 分页获取用户列表
     *
     * @param dto
     * @return
     */
    @Override
    public JsonResult<List<UserVO>> pageUserList(PageDTO dto, String userName, String loginId, Integer groupId) {
//        IPage<User> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        Integer pageNumber = dto.getPageNumber();
        Integer pageSize = dto.getPageSize();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (dto.getStartTime() != null && dto.getEndTime() != null) {
            queryWrapper.lambda().between(User::getCreateTime, dto.getStartTime(), dto.getEndTime());
        }
//        if (userName != null) {
//            queryWrapper.lambda().eq(User::getUserType, NumericalConstants.ZERO);
//            queryWrapper.lambda().eq(User::getUserName, AESUtils.encrypt(userName));
//        }
        if (StringUtils.isNotBlank(loginId)) {
            queryWrapper.lambda().eq(User::getUserType, NumericalConstants.ONE);
//            queryWrapper.lambda().eq(User::getLoginId, AESUtils.encrypt(loginId));
        }
        if (groupId != null) {
            queryWrapper.lambda().eq(User::getGroupId, groupId);
        }
        //排除admin
        queryWrapper.lambda().ne(User::getParentId, NumericalConstants.NEGATIVE_ONE);
        queryWrapper.select(User.class, info -> !info.getColumn().equals("password"));
        queryWrapper.orderByDesc("create_time");
        List<User> users = userMapper.selectList(queryWrapper);
        long total = NumericalConstants.ZERO;
        List<UserVO> dataList = new ArrayList<>();
        if (CollectionUtils.isEmpty(users)) {
            return JsonResult.success(dataList, total);
        }
        if (StringUtils.isAllBlank(userName, loginId)) {
            total = users.size();
            users = DataUtil.pagingByList(users, pageSize, pageNumber);
        } else {
            List<User> tempUserList = new LinkedList<>();
            for (User user : users) {
                String tempUserName = user.getUserName();
                String tempLoginId = user.getLoginId();
                if (StringUtils.isNotBlank(userName) && tempUserName.contains(userName)) {
                    tempUserList.add(user);
                } else {
                    if (!StringUtils.isAnyBlank(loginId, tempLoginId) && tempLoginId.contains(loginId)) {
                        tempUserList.add(user);
                    }
                }
            }
            if (CollectionUtils.isEmpty(tempUserList)) {
                return JsonResult.success(dataList, total);
            }
            total = tempUserList.size();
            users = DataUtil.pagingByList(tempUserList, pageSize, pageNumber);
        }

        List<Integer> groupIds = users.stream().map(User::getGroupId).collect(Collectors.toList());
        Map<Integer, PersonGroup> personGroupMap = null;
        if (!CollectionUtils.isEmpty(groupIds)) {
            List<PersonGroup> personGroups = personGroupMapper.selectList(Wrappers.<PersonGroup>lambdaQuery()
                    .in(PersonGroup::getGroupId, groupIds).eq(PersonGroup::getGroupType, NumericalConstants.ONE));
            if (!CollectionUtils.isEmpty(personGroups)) {
                personGroupMap = personGroups.stream().collect(Collectors.toMap(PersonGroup::getGroupId, Function.identity()));
            }
        }

        for (User item : users) {
            //            List<Long> roleIdList = userRoleMapper.selectUserRoleIdList(item.getUserId());
            UserRole userRole = userRoleMapper.selectOne(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, item.getUserId()));
            UserVO userVO = UserVO.builder().build();
            BeanUtils.copyProperties(item, userVO);
            String str = redisCached.get(RedisConstant.USER_LOGIN_LOCK + item.getUserId());
            userVO.setIsLock(StringUtils.isNotBlank(str) ? NumericalConstants.ONE : NumericalConstants.TWO);
            if (userRole != null) {
                userVO.setRoleId(userRole.getRoleId());
            }
            if (!CollectionUtils.isEmpty(personGroupMap)) {
                PersonGroup personGroup = personGroupMap.get(item.getGroupId());
                if (personGroup != null) {
                    userVO.setGroupName(personGroup.getGroupName());
                }
            }
            dataList.add(userVO);
        }
        return JsonResult.success(dataList, total);
    }

    /**
     * 设置访问权限
     *
     * @param userId
     * @param isAccess
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/9/2 15:41
     */
    @Override
    public JsonResult setAccessAuth(Long userId, Integer isAccess, String ip) {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        User oldUser = userMapper.selectById(userId);
        if (oldUser == null) {
            return JsonResult.fail(JsonResultEnum.USER_NOT_EXIST);
        }
        if (!isAccess.equals(NumericalConstants.ONE) && !isAccess.equals(NumericalConstants.TWO)) {
            return JsonResult.fail(JsonResultEnum.PARAM_ERROR);
        }
        User user = new User();
        user.setUserId(userId);
        user.setIsAccess(isAccess);
        //超过三个月设为休眠状态，在此处修改最后登录时间
        if (isAccess.equals(NumericalConstants.ONE) && DateUtils.differentDays(oldUser.getLastLoginTime(), new Date()) >= 90) {
            user.setLastLoginTime(new Date());
        }
        if (userMapper.updateById(user) > NumericalConstants.ZERO) {
            UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.ONE, ip, tokenUser);
            //允许访问
            if (isAccess.equals(NumericalConstants.ONE)) {
                userOperateLog.setContentOperate(oldUser.getUserName() + "账号禁止访问设置为允许访问");
            } else {
                userOperateLog.setContentOperate(oldUser.getUserName() + "账号允许访问设置为禁止访问");
            }
            userOperateLogMapper.insert(userOperateLog);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取登录用户信息
     *
     * @param sessionId
     * @return com.bsj.power.common.config.global.TokenUser
     * @author ljx
     * @time 2024/9/2 16:47
     */
    @Override
    public TokenUser getLoginInfo(String sessionId) {
        TokenUser tokenUser = null;
        Object loginUser = StpUtil.getTokenSessionByToken(sessionId).get("loginUser");
        if (loginUser != null) {
            tokenUser = (TokenUser) loginUser;
        }
        return tokenUser;
    }

    /**
     * 取消锁定
     *
     * @param userId
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/9/27 15:09
     */
    @Override
    @Transactional
    public JsonResult cancelLock(Integer userId, String ip) {
        ParamCheckUtil.isNull(userId);
        User user = userMapper.selectById(userId);
        ParamCheckUtil.isNull(user, JsonResultEnum.USER_NOT_EXIST);
        //清除锁定
        redisCached.del(RedisConstant.USER_LOGIN_LOCK + userId);
        //清除次数
        redisCached.del(RedisConstant.LOGIN_ALREADY_FAIL_NUMBER + userId);
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        UserOperateLog userOperateLog = new UserOperateLog(NumericalConstants.TWO, NumericalConstants.ONE, ip, tokenUser);
        //允许访问
        userOperateLog.setContentOperate(user.getUserName() + "账号取消锁定");
        userOperateLogMapper.insert(userOperateLog);
        return JsonResult.success();
    }
}
